home *** CD-ROM | disk | FTP | other *** search
/ Software Vault: The Gold Collection / Software Vault - The Gold Collection (American Databankers) (1993).ISO / cdr07 / oleo130s.zip / OLEO130S.TAR / oleo-1.3 / byte-compile.c < prev    next >
C/C++ Source or Header  |  1993-03-19  |  22KB  |  870 lines

  1. /*    Copyright (C) 1990, 1992, 1993 Free Software Foundation, Inc.
  2.  
  3. This file is part of Oleo, the GNU Spreadsheet.
  4.  
  5. Oleo is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2, or (at your option)
  8. any later version.
  9.  
  10. Oleo is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13. GNU General Public License for more details.
  14.  
  15. You should have received a copy of the GNU General Public License
  16. along with Oleo; see the file COPYING.  If not, write to
  17. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  18.  
  19. #include "funcdef.h"
  20. #include <stdio.h>
  21.  
  22. #define obstack_chunk_alloc ck_malloc
  23. #define obstack_chunk_free free
  24. #include "obstack.h"
  25.  
  26. #include "sysdef.h"
  27. #include "global.h"
  28. #include "node.h"
  29. #include "eval.h"
  30. #include "math.h"
  31. #include "hash.h"
  32. #include "ref.h"
  33.  
  34.  
  35. #ifdef __STDC__
  36. extern int yyparse (void);
  37. #else
  38. extern int yyparse ();
  39. #endif
  40.  
  41. extern struct function busi_funs[];
  42. extern struct function string_funs[];
  43. extern struct function cells_funs[];
  44. extern char *instr;
  45. extern int parse_error;
  46. extern struct node *parse_return;
  47. extern void sort ();
  48.  
  49.  
  50. #ifdef __STDC__
  51. static void add_backpatch (unsigned, unsigned);
  52. #else
  53. static void add_backpatch ();
  54. #endif
  55.  
  56. struct backpatch
  57.   {
  58.     unsigned from, to;
  59.   };
  60.  
  61. static struct backpatch *patches;
  62. static int patches_allocated;
  63. static int patches_used;
  64. static void *fn_stack;
  65. static void *str_stack;
  66. struct obstack tmp_mem;
  67. void *tmp_mem_start;
  68.  
  69.  
  70. #define V (void(*)())
  71.  
  72. /* These have to go in some file or other, so it is stuck in here (for now).
  73.  */
  74. struct function the_funs[] =
  75. {
  76.   {0, X_A0, "", 0, "<END>"},
  77.   {0, X_A0, "", 0, "<DUMMY1>"},
  78.  
  79.   {C_IF | R | INF (1), X_A1 | X_J, "D", 0, "?"},
  80.   {C_IF | R | INF (1), X_A1 | X_JL, "D", 0, "?"},
  81.   {C_IF, X_A1 | X_J, "D", 0, "if"},
  82.   {C_IF, X_A1 | X_JL, "D", 0, "if"},
  83.   {C_ANDOR, X_A1 | X_J, "D", 0, "and"},
  84. /* { C_ANDOR|L|INF(3), X_A1, "DD", 0,        "&" }, */
  85.   {C_ANDOR, X_A1 | X_JL, "D", 0, "and"},
  86. /* { C_ANDOR|L|INF(3), X_A1, "DD", 0,        "&" }, */
  87.   {C_ANDOR, X_A1 | X_J, "D", 0, "or"},
  88. /* { C_ANDOR|L|INF(2), X_A1, "DD", 0,        "|" }, */
  89.   {C_ANDOR, X_A1 | X_JL, "D", 0, "or"},
  90. /* { C_ANDOR|L|INF(2), X_A1, "DD", 0,        "|" }, */
  91.   {C_STR, X_A0 | X_J, "", 0, "\"%s\""},
  92.   {C_STR, X_A0 | X_JL, "", 0, "\"%s\""},
  93.  
  94.   {C_CELL, X_A0, "", 0, "$%s$%u"},
  95.   {C_CELL, X_A0, "", 0, "$%s%u"},
  96.   {C_CELL, X_A0, "", 0, "%s$%u"},
  97.   {C_CELL, X_A0, "", 0, "%s%u"},
  98.   {C_RANGE, X_A0, "", 0, "$%s$%u:$%s$%u"},
  99.   {C_RANGE, X_A0, "", 0, "$%s%u:$%s$%u"},
  100.   {C_RANGE, X_A0, "", 0, "$%s$%u:$%s%u"},
  101.   {C_RANGE, X_A0, "", 0, "$%s%u:$%s%u"},
  102.   {C_RANGE, X_A0, "", 0, "%s$%u:$%s$%u"},
  103.   {C_RANGE, X_A0, "", 0, "%s%u:$%s$%u"},
  104.   {C_RANGE, X_A0, "", 0, "%s$%u:$%s%u"},
  105.   {C_RANGE, X_A0, "", 0, "%s%u:$%s%u"},
  106.   {C_RANGE, X_A0, "", 0, "$%s$%u:%s$%u"},
  107.   {C_RANGE, X_A0, "", 0, "$%s%u:%s$%u"},
  108.   {C_RANGE, X_A0, "", 0, "$%s$%u:%s%u"},
  109.   {C_RANGE, X_A0, "", 0, "$%s%u:%s%u"},
  110.   {C_RANGE, X_A0, "", 0, "%s$%u:%s$%u"},
  111.   {C_RANGE, X_A0, "", 0, "%s%u:%s$%u"},
  112.   {C_RANGE, X_A0, "", 0, "%s$%u:%s%u"},
  113.   {C_RANGE, X_A0, "", 0, "%s%u:%s%u"},
  114.  
  115.   {C_CONST, X_A0, "", 0, tname},
  116.   {C_CONST, X_A0, "", 0, fname},
  117.  
  118.   {C_CONST, X_A0, "", 0, iname},
  119.   {C_CONST, X_A0, "", 0, mname},
  120.   {C_CONST, X_A0, "", 0, nname},
  121.   {C_ERR, X_A0 | X_J, "", 0, "%s"},
  122.   {C_FLT, X_A0, "", 0, "%.15g"},
  123.   {C_INT, X_A0, "", 0, "%ld"},
  124.  
  125.   {C_VAR, X_A0, "", 0, "%s"},
  126.  
  127.   {C_UNA, X_A1, "F", 0, "-"},
  128.   {C_UNA, X_A1, "B", 0, "!"},
  129.  
  130.   {C_INF | L | INF (6), X_A2, "NN", 0, "-"},
  131.   {C_INF | L | INF (7), X_A2, "NN", 0, "/"},
  132.   {C_INF | L | INF (7), X_A2, "NN", 0, "%"},
  133.   {C_INF | L | INF (7), X_A2, "NN", 0, "*"},
  134.   {C_INF | L | INF (6), X_A2, "NN", 0, "+"},
  135.   {C_INF | L | INF (2), X_A2, "SS", 0, "&"},
  136.   {C_INF | N | INF (4), X_A2, "AA", 0, "="},
  137.   {C_INF | N | INF (5), X_A2, "AA", 0, ">="},
  138.   {C_INF | N | INF (5), X_A2, "AA", 0, ">"},
  139.   {C_INF | N | INF (5), X_A2, "AA", 0, "<"},
  140.   {C_INF | N | INF (5), X_A2, "AA", 0, "<="},
  141.   {C_INF | N | INF (4), X_A2, "AA", 0, "!="},
  142.   {C_INF | R | INF (8), X_A2, "FF", V pow, "^"},
  143.  
  144.   {C_FN0, X_A0, "", 0, "pi"},
  145.   {C_FN0X, X_A0, "", 0, "row"},
  146.   {C_FN0X, X_A0, "", 0, "col"},
  147.   {C_FN0 | C_T, X_A0, "", 0, "now"},
  148.  
  149.   {C_FN1, X_A1, "F", V fabs, "abs"},
  150.   {C_FN1, X_A1, "F", V acos, "acos"},
  151.   {C_FN1, X_A1, "F", V asin, "asin"},
  152.   {C_FN1, X_A1, "F", V atan, "atan"},
  153.   {C_FN1, X_A1, "F", V ceil, "ceil"},
  154.   {C_FN1, X_A1, "F", V to_int, "int"},
  155.   {C_FN1, X_A1, "F", V floor, "floor"},
  156.   {C_FN1, X_A1, "F", V cos, "cos"},
  157.   {C_FN1, X_A1, "F", V dtr, "dtr"},
  158.   {C_FN1, X_A1, "F", V exp, "exp"},
  159.   {C_FN1, X_A1, "F", V log, "log"},
  160.   {C_FN1, X_A1, "F", V log10, "log10"},
  161.   {C_FN1, X_A1, "F", V rtd, "rtd"},
  162.   {C_FN1, X_A1, "F", V sin, "sin"},
  163.   {C_FN1, X_A1, "F", V sqrt, "sqrt"},
  164.   {C_FN1, X_A1, "F", V tan, "tan"},
  165.   {C_FN1, X_A1, "I", 0, "ctime"},
  166.   {C_FN1, X_A1, "A", 0, "negate"},
  167.   {C_FN1, X_A1, "A", 0, "not"},
  168.   {C_FN1, X_A1, "A", 0, "iserr"},
  169.   {C_FN1, X_A1, "A", 0, "isnum"},
  170.  
  171.   {C_FN1 | C_T, X_A1, "I", 0, "rnd"},
  172.   {C_FN1, X_A1, "R", 0, "rows"},
  173.   {C_FN1, X_A1, "R", 0, "cols"},
  174.   {C_FN2, X_A2, "FF", V atan2, "atan2"},
  175.   {C_FN2, X_A2, "FF", V hypot, "hypot"},
  176.   {C_FN2, X_A2, "FI", 0, "fixed"},
  177.   {C_FN2, X_A2, "AA", 0, "iferr"},
  178.   {C_FN2, X_A2, "RI", 0, "index"},
  179.   {C_FN3, X_A3, "RII", 0, "index"},
  180.   {C_FNN, X_AN, "IAAA", 0, "oneof"},
  181.  
  182.   {C_FNN, X_AN, "SIIA", 0, "file"},
  183.   {C_FNN, X_AN, "EEEE", 0, "sum"},
  184.   {C_FNN, X_AN, "EEEE", 0, "prod"},
  185.   {C_FNN, X_AN, "EEEE", 0, "avg"},
  186.   {C_FNN, X_AN, "EEEE", 0, "std"},
  187.   {C_FNN, X_AN, "EEEE", 0, "max"},
  188.   {C_FNN, X_AN, "EEEE", 0, "min"},
  189.   {C_FNN, X_AN, "EEEE", 0, "count"},
  190.   {C_FNN, X_AN, "EEEE", 0, "var"},
  191.  
  192. };
  193.  
  194. #ifdef USE_DLD
  195. int n_usr_funs;
  196. struct function **usr_funs;
  197. int *usr_n_funs;
  198. #else
  199. int n_usr_funs = 3;
  200. static struct function *__usr_funs[] =
  201. {
  202.   busi_funs,
  203.   string_funs,
  204.   cells_funs,
  205. };
  206. static int __usr_n_funs[] =
  207. {
  208.   18, 11, 10
  209. };
  210.  
  211. struct function **usr_funs = __usr_funs;
  212. int *usr_n_funs = __usr_n_funs;
  213. #endif
  214.  
  215. /* ... A whole huge empty space, then ... */
  216. struct function skip_funs[] =
  217. {
  218.   {C_SKIP, X_A0 | X_J, "", 0, "<Skip %u>"},
  219.   {C_SKIP, X_A0 | X_JL, "", 0, "<SkipL %u>"},
  220. };
  221.  
  222. /* The memory allocated here is used for several things, but byte_compile
  223.    is a small file, so it might as well be here */
  224. void
  225. init_mem ()
  226. {
  227.   int n;
  228.  
  229.   parse_hash = hash_new ();
  230.   hash_insert (parse_hash, the_funs[F_IF].fn_str, &the_funs[F_IF]);
  231.   hash_insert (parse_hash, the_funs[AND].fn_str, &the_funs[AND]);
  232.   hash_insert (parse_hash, the_funs[OR].fn_str, &the_funs[OR]);
  233.   for (n = F_PI; n < USR1; n++)
  234.     hash_insert (parse_hash, the_funs[n].fn_str, &the_funs[n]);
  235. #ifndef USE_DLD
  236.   for (n = 0; n < n_usr_funs; n++)
  237.     {
  238.       int nn;
  239.  
  240.       for (nn = 0; usr_funs[n][nn].fn_str; nn++)
  241.     hash_insert (parse_hash, usr_funs[n][nn].fn_str, &usr_funs[n][nn]);
  242. #ifdef TEST
  243.       if (usr_n_funs[n] != nn)
  244.     {
  245.       fprintf (stderr, "Usr_n_funs[%d]%d!=%d", n, usr_n_funs[n], nn);
  246.       usr_n_funs[n] = nn;
  247.  
  248.     }
  249. #endif
  250.     }
  251. #endif
  252.   fn_stack = init_stack ();
  253.   str_stack = init_stack ();
  254.   obstack_begin (&tmp_mem, 400);
  255.   tmp_mem_start = obstack_alloc (&tmp_mem, 0);
  256. }
  257.  
  258. #ifdef USE_DLD
  259. void
  260. add_usr_funs (new_funs)
  261.      struct function *new_funs;
  262. {
  263.   int n;
  264.  
  265.   n_usr_funs++;
  266.   usr_funs = usr_funs ? ck_realloc (usr_funs, n_usr_funs * sizeof (struct function *)) : ck_malloc (sizeof (struct function *));
  267.   usr_n_funs = usr_n_funs ? ck_realloc (usr_n_funs, n_usr_funs * sizeof (int)) : ck_malloc (sizeof (int));
  268.  
  269.   usr_funs[n_usr_funs - 1] = new_funs;
  270.   for (n = 0; new_funs[n].fn_str; n++)
  271.     hash_insert (parse_hash, new_funs[n].fn_str, &new_funs[n]);
  272.   usr_n_funs[n_usr_funs - 1] = n;
  273. }
  274.  
  275. #endif
  276.  
  277. /* Stash away a backpatch for future editing. */
  278. static void
  279. add_backpatch (from, to)
  280.      unsigned from;
  281.      unsigned to;
  282. {
  283.   if (!patches)
  284.     {
  285.       patches_allocated = 5;
  286.       patches = (struct backpatch *) ck_malloc (patches_allocated * sizeof (struct backpatch));
  287.       patches_used = 0;
  288.     }
  289.   if (patches_allocated == patches_used)
  290.     {
  291.       patches_allocated *= 2;
  292.       patches = (struct backpatch *) ck_realloc (patches, patches_allocated * sizeof (struct backpatch));
  293.     }
  294.   patches[patches_used].from = from;
  295.   patches[patches_used].to = to;
  296.   patches_used++;
  297. }
  298.  
  299. static int
  300. cmp_patch (n1, n2)
  301.      int n1;
  302.      int n2;
  303. {
  304.   int ret;
  305.  
  306.   ret = (patches[n1].from == patches[n2].from) ? patches[n1].to - patches[n2].to : patches[n1].from - patches[n2].from;
  307.   return ret;
  308. }
  309.  
  310. static void
  311. swp_patch (n1, n2)
  312.      int n1;
  313.      int n2;
  314. {
  315.   struct backpatch tmp;
  316.  
  317.   tmp = patches[n1];
  318.   patches[n1] = patches[n2];
  319.   patches[n2] = tmp;
  320. }
  321.  
  322. static void
  323. rot_patch (n1, n2)
  324.      int n1;
  325.      int n2;
  326. {
  327.   struct backpatch tmp;
  328.   tmp = patches[n2];
  329.   while (n2 > n1)
  330.     {
  331.       patches[n2] = patches[n2 - 1];
  332.       --n2;
  333.     }
  334.   patches[n2] = tmp;
  335. }
  336.  
  337.  
  338. /* This takes an ascii string and returns a pointer to the byte-compiled
  339.    result.  It calls yyparse() to do the actual parsing.  This is complicated
  340.    only because yyparse returns a parse tree which needs to be turned into
  341.    postfix compiled bytes.  This is further complicated by the presence of
  342.    forward branches in the byte-compiled code.  That's what the backpatch
  343.    stuff is for.
  344.  
  345.    It'd be nice if oneof() could compile into
  346.    arg1
  347.    ONEOF n_possibilities
  348.    JUMP poss1
  349.    JUMP poss2
  350.    JUMP poss3
  351.    ...
  352.    JUMP error
  353.    {poss 1}
  354.    JUMP end
  355.    {poss 2}
  356.    JUMP end
  357.    ...
  358.    end: {rest of expression}
  359.    instead of the simplistic (and slow-to-execute) version currently used
  360.  
  361.    It'd also be nice if byte-compiled expressions could have *BIG*
  362.    subexpressions, instead of silently failing as they do now.  Error checking
  363.    and a way to encode longer branches would be a *good* idea.
  364.  */
  365. unsigned char *
  366. parse_and_compile (string)
  367.      char *string;
  368. {
  369.   struct node *new_node;
  370.   struct node *node;
  371.   const struct function *f;
  372.   unsigned char *ret;
  373.   int n;
  374.   unsigned buf_siz;
  375.   int need_relax;
  376.   int byte;
  377.  
  378.   instr = string;
  379.   parse_error = 0;
  380.   patches_used = 0;
  381.   if (yyparse () || parse_error)
  382.     {
  383.       ret = ck_malloc (strlen (string) + 5);
  384.       ret[0] = CONST_ERR;
  385.       ret[1] = 2;
  386.       ret[2] = parse_error;
  387.       ret[3] = ENDCOMP;
  388.       strcpy ((char *) &ret[4], string);
  389.       (void) obstack_free (&tmp_mem, tmp_mem_start);
  390.       return ret;
  391.     }
  392.  
  393.   node = parse_return;
  394.   if (!node)
  395.     return 0;
  396.  
  397. loop:
  398.   if (node->comp_value < USR1)
  399.     {
  400.       f = &the_funs[node->comp_value];
  401.     }
  402.   else if (node->comp_value < SKIP)
  403.     {
  404.       n = node->sub_value;
  405.       f = &usr_funs[node->comp_value - USR1][n];
  406.     }
  407.   else
  408.     {
  409.       f = &skip_funs[node->comp_value - SKIP];
  410.     }
  411.   byte = node->comp_value;
  412.  
  413. #ifdef TEST
  414.   if (!f)
  415.     panic ("f is zero in byte_compile!");
  416. #endif
  417.   switch (GET_COMP (f->fn_comptype))
  418.     {
  419.     case C_IF:
  420.       /* if compiles to
  421.            test-code IF amt-to-skip-on-false true-code SKIP
  422.                amt-to-skip-on-true false-code */
  423.       if (node->n_x.v_subs[0])
  424.     {
  425.       if (node->n_x.v_subs[0]->n_x.v_subs[0])
  426.         {
  427.           /* Put out the test-code */
  428.           push_stack (fn_stack, node);
  429.           new_node = node->n_x.v_subs[0]->n_x.v_subs[0];
  430.           node->n_x.v_subs[0]->n_x.v_subs[0] = 0;
  431.           node = new_node;
  432.           goto loop;
  433.         }
  434.       /* Put out IF, null-byte to backpatch */
  435.       (void) obstack_1grow (&tmp_mem, byte);
  436.       node->add_byte = obstack_object_size (&tmp_mem);
  437.       (void) obstack_1grow (&tmp_mem, 0);
  438.  
  439.       /* put out true-code */
  440.       push_stack (fn_stack, node);
  441.       new_node = node->n_x.v_subs[0]->n_x.v_subs[1];
  442.       node->n_x.v_subs[0] = 0;
  443.       node = new_node;
  444.       goto loop;
  445.     }
  446.       if (node->n_x.v_subs[1])
  447.     {
  448.  
  449.       (void) obstack_1grow (&tmp_mem, (char)SKIP);
  450.       (void) obstack_1grow (&tmp_mem, 0);
  451.       add_backpatch (node->add_byte, obstack_object_size (&tmp_mem));
  452.       node->add_byte = obstack_object_size (&tmp_mem) - 1;
  453.  
  454.       push_stack (fn_stack, node);
  455.       new_node = node->n_x.v_subs[1];
  456.       node->n_x.v_subs[1] = 0;
  457.       node = new_node;
  458.       goto loop;
  459.     }
  460.       add_backpatch (node->add_byte, obstack_object_size (&tmp_mem));
  461.       break;
  462.  
  463.     case C_ANDOR:
  464.       if (node->n_x.v_subs[0])
  465.     {
  466.       push_stack (fn_stack, node);
  467.       new_node = node->n_x.v_subs[0];
  468.       node->n_x.v_subs[0] = 0;
  469.       node = new_node;
  470.       goto loop;
  471.     }
  472.       if (node->n_x.v_subs[1])
  473.     {
  474.       (void) obstack_1grow (&tmp_mem, byte);
  475.       node->add_byte = obstack_object_size (&tmp_mem);
  476.       (void) obstack_1grow (&tmp_mem, 0);    /* for backpatching */
  477.       push_stack (fn_stack, node);
  478.       new_node = node->n_x.v_subs[1];
  479.       node->n_x.v_subs[1] = 0;
  480.       node = new_node;
  481.       goto loop;
  482.     }
  483.       add_backpatch (node->add_byte, obstack_object_size (&tmp_mem));
  484.       break;
  485.  
  486.     case C_ERR:
  487.       (void) obstack_1grow (&tmp_mem, byte);
  488.       node->add_byte = obstack_object_size (&tmp_mem);
  489.       (void) obstack_1grow (&tmp_mem, 0);
  490.       (void) obstack_1grow (&tmp_mem, node->n_x.v_int);
  491.       node->n_x.v_string = ename[node->n_x.v_int];
  492.       push_stack (str_stack, node);
  493.       break;
  494.  
  495.     case C_FLT:
  496.       (void) obstack_1grow (&tmp_mem, byte);
  497.       (void) obstack_grow (&tmp_mem, &(node->n_x.v_float), sizeof (double));
  498.       break;
  499.  
  500.     case C_INT:
  501.       (void) obstack_1grow (&tmp_mem, byte);
  502.       (void) obstack_grow (&tmp_mem, &(node->n_x.v_int), sizeof (long));
  503.       break;
  504.  
  505.     case C_STR:
  506.       (void) obstack_1grow (&tmp_mem, byte);
  507.       node->add_byte = obstack_object_size (&tmp_mem);
  508.       (void) obstack_1grow (&tmp_mem, 0);
  509.       push_stack (str_stack, node);
  510.       break;
  511.  
  512.     case C_VAR:
  513.       add_ref_to (obstack_object_size (&tmp_mem));
  514.       add_var_ref (node->n_x.v_var);
  515.       (void) obstack_1grow (&tmp_mem, byte);
  516.       (void) obstack_grow (&tmp_mem, &(node->n_x.v_var), sizeof (struct var *));
  517.       break;
  518.  
  519.     case C_CELL:
  520.       add_ref_to (obstack_object_size (&tmp_mem));
  521.       add_ref (node->n_x.v_rng.lr, node->n_x.v_rng.lc);
  522.       (void) obstack_1grow (&tmp_mem, byte);
  523. #if BITS_PER_CELLREF==16
  524.       (void) obstack_1grow (&tmp_mem, node->n_x.v_rng.lr >> 8);
  525.       (void) obstack_1grow (&tmp_mem, node->n_x.v_rng.lr);
  526.       (void) obstack_1grow (&tmp_mem, node->n_x.v_rng.lc >> 8);
  527.       (void) obstack_1grow (&tmp_mem, node->n_x.v_rng.lc);
  528. #else
  529. #if BITS_PER_CELLREF==8
  530.       (void) obstack_1grow (&tmp_mem, node->n_x.v_rng.lr);
  531.       (void) obstack_1grow (&tmp_mem, node->n_x.v_rng.lc);
  532. #else
  533.       Insert appropriate code here
  534. #endif
  535. #endif
  536.         break;
  537.  
  538.     case C_RANGE:
  539.       add_ref_to (obstack_object_size (&tmp_mem));
  540.       add_range_ref (&(node->n_x.v_rng));
  541.       (void) obstack_1grow (&tmp_mem, byte);
  542.       (void) obstack_grow (&tmp_mem, &(node->n_x.v_rng), sizeof (struct rng));
  543.       break;
  544.  
  545.     case C_FN0X:
  546.       add_ref_to (obstack_object_size (&tmp_mem));
  547.       /* FALLTHROUGH */
  548.     case C_FN0:
  549.     case C_CONST:
  550.     add_byte:
  551.       if (f->fn_comptype & C_T)
  552.     add_timer_ref (obstack_object_size (&tmp_mem));
  553.       (void) obstack_1grow (&tmp_mem, byte);
  554.       if (byte >= USR1 && byte < SKIP)
  555.     (void) obstack_1grow (&tmp_mem, (int) node->sub_value);
  556.       break;
  557.  
  558.     case C_FN1:
  559.     case C_UNA:
  560.       if (node->n_x.v_subs[0])
  561.     {
  562.       push_stack (fn_stack, node);
  563.       new_node = node->n_x.v_subs[0];
  564.       node->n_x.v_subs[0] = 0;
  565.       node = new_node;
  566.       goto loop;
  567.     }
  568.       goto add_byte;
  569.  
  570.     case C_FN2:
  571.     case C_INF:
  572.       if (node->n_x.v_subs[0])
  573.     {
  574.       push_stack (fn_stack, node);
  575.       new_node = node->n_x.v_subs[0];
  576.       node->n_x.v_subs[0] = 0;
  577.       node = new_node;
  578.       goto loop;
  579.     }
  580.       if (node->n_x.v_subs[1])
  581.     {
  582.       push_stack (fn_stack, node);
  583.       new_node = node->n_x.v_subs[1];
  584.       node->n_x.v_subs[1] = 0;
  585.       node = new_node;
  586.       goto loop;
  587.     }
  588.       goto add_byte;
  589.  
  590.     case C_FN3:
  591.       if (node->n_x.v_subs[0])
  592.     {
  593.       if (node->n_x.v_subs[0]->n_x.v_subs[0])
  594.         {
  595.           push_stack (fn_stack, node);
  596.           new_node = node->n_x.v_subs[0]->n_x.v_subs[0];
  597.           node->n_x.v_subs[0]->n_x.v_subs[0] = 0;
  598.           node = new_node;
  599.           goto loop;
  600.         }
  601.       push_stack (fn_stack, node);
  602.       new_node = node->n_x.v_subs[0]->n_x.v_subs[1];
  603.       node->n_x.v_subs[0] = 0;
  604.       node = new_node;
  605.       goto loop;
  606.     }
  607.       if (node->n_x.v_subs[1])
  608.     {
  609.       push_stack (fn_stack, node);
  610.       new_node = node->n_x.v_subs[1];
  611.       node->n_x.v_subs[1] = 0;
  612.       node = new_node;
  613.       goto loop;
  614.     }
  615.       goto add_byte;
  616.  
  617.     case C_FN4:
  618.       if (node->n_x.v_subs[0])
  619.     {
  620.       if (node->n_x.v_subs[0]->n_x.v_subs[0])
  621.         {
  622.           push_stack (fn_stack, node);
  623.           new_node = node->n_x.v_subs[0]->n_x.v_subs[0];
  624.           node->n_x.v_subs[0]->n_x.v_subs[0] = 0;
  625.           node = new_node;
  626.           goto loop;
  627.         }
  628.       push_stack (fn_stack, node);
  629.       new_node = node->n_x.v_subs[0]->n_x.v_subs[1];
  630.       node->n_x.v_subs[0] = 0;
  631.       node = new_node;
  632.       goto loop;
  633.     }
  634.       if (node->n_x.v_subs[1])
  635.     {
  636.       if (node->n_x.v_subs[1]->n_x.v_subs[0])
  637.         {
  638.           push_stack (fn_stack, node);
  639.           new_node = node->n_x.v_subs[1]->n_x.v_subs[0];
  640.           node->n_x.v_subs[1]->n_x.v_subs[0] = 0;
  641.           node = new_node;
  642.           goto loop;
  643.         }
  644.       push_stack (fn_stack, node);
  645.       new_node = node->n_x.v_subs[1]->n_x.v_subs[1];
  646.       node->n_x.v_subs[1] = 0;
  647.       node = new_node;
  648.       goto loop;
  649.     }
  650.       goto add_byte;
  651.  
  652.     case C_FNN:
  653.       if (node->n_x.v_subs[1])
  654.     {
  655.       if (node->add_byte == 0)
  656.         for (new_node = node; new_node->n_x.v_subs[1]; new_node = new_node->n_x.v_subs[1])
  657.           node->add_byte++;
  658.       for (new_node = node; new_node->n_x.v_subs[1]->n_x.v_subs[1]; new_node = new_node->n_x.v_subs[1])
  659.         ;
  660.       push_stack (fn_stack, node);
  661.       node = new_node->n_x.v_subs[1]->n_x.v_subs[0];
  662.       new_node->n_x.v_subs[1] = 0;
  663.       goto loop;
  664.     }
  665.       (void) obstack_1grow (&tmp_mem, byte);
  666.       if (byte >= USR1 && byte < SKIP)
  667.     (void) obstack_1grow (&tmp_mem, (int) node->sub_value);
  668.       (void) obstack_1grow (&tmp_mem, node->add_byte);
  669.       break;
  670.  
  671.     default:
  672.       panic ("Bad comptype %d", f->fn_comptype);
  673.     }
  674.   node = (struct node *) pop_stack (fn_stack);
  675.   if (node)
  676.     goto loop;
  677.  
  678.   (void) obstack_1grow (&tmp_mem, 0);
  679.  
  680.   while (node = pop_stack (str_stack))
  681.     {
  682.       add_backpatch (node->add_byte, obstack_object_size (&tmp_mem));
  683.       (void) obstack_grow (&tmp_mem, node->n_x.v_string, strlen (node->n_x.v_string) + 1);
  684.     }
  685.  
  686.   buf_siz = obstack_object_size (&tmp_mem);
  687.   ret = (unsigned char *) ck_malloc (buf_siz);
  688.   bcopy (obstack_finish (&tmp_mem), ret, buf_siz);
  689.  
  690.   need_relax = 0;
  691.   for (n = 0; n < patches_used; n++)
  692.     {
  693.       long offset;
  694.  
  695.       offset = (patches[n].to - patches[n].from) - 1;
  696.       if (offset < 0 || offset > 255)
  697.     need_relax++;
  698.       else
  699.     ret[patches[n].from] = offset;
  700.     }
  701.   if (need_relax)
  702.     {
  703.       int n_lo;
  704.       long offset;
  705.       int start;
  706.  
  707.       /* ... Sort the patches list ... */
  708.       sort (patches_used, cmp_patch, swp_patch, rot_patch);
  709.  
  710.       while (need_relax)
  711.     {
  712.       ret = ck_realloc (ret, buf_siz + need_relax);
  713.       for (n_lo = 0; n_lo < patches_used; n_lo++)
  714.         {
  715.           offset = (patches[n_lo].to - patches[n_lo].from) - 1;
  716.           if (offset < 0 || offset > 255 - need_relax)
  717.         break;
  718.         }
  719.  
  720.       /* n_lo points to the first jump that may need to be relaxed */
  721.       for (n = n_lo; n < patches_used; n++)
  722.         {
  723.           offset = (patches[n].to - patches[n].from) - 1;
  724.           if (offset < 0 || offset > 255)
  725.         {
  726.           int nn;
  727.  
  728.           start = patches[n].from;
  729.  
  730.           ret[start - 1]++;    /* Translate insn to LONG */
  731.           ret[start] = offset;
  732.           bcopy (&ret[start + 1], &ret[start + 2], buf_siz - start);
  733.           ret[start + 1] = offset >> 8;
  734.           need_relax--;
  735.           buf_siz++;
  736.           for (nn = 0; nn < patches_used; nn++)
  737.             {
  738.               if (patches[nn].from > start)
  739.             patches[nn].from++;
  740.               if (patches[nn].to > start)
  741.             patches[nn].to++;
  742.               if (patches[nn].from < start && patches[nn].to > start && ret[patches[nn].from]++ == 255)
  743.             {
  744.               if (ret[patches[nn].from - 1] & 01)
  745.                 ret[patches[nn].from + 1]++;
  746.               else
  747.                 need_relax++;
  748.             }
  749.             }
  750.         }
  751.         }
  752.     }
  753.     }
  754.  
  755.   (void) obstack_free (&tmp_mem, tmp_mem_start);
  756.  
  757.   patches_used = 0;
  758.  
  759.   return ret;
  760. }
  761.  
  762. /* Back when strings stored a char*, they needed to be freed when a
  763.    byte-compiled expression was freed.  Now that they're appended to the end,
  764.    they don't need to be specially freed anymore.
  765.  */
  766. void
  767. byte_free (form)
  768.      unsigned char *form;
  769. {
  770.   /* no longer needed
  771.     unsigned char *f;
  772.  
  773.     for(f=form;*f;f++) {
  774.         switch(*f) {
  775.         case IF:
  776.         case F_IF:
  777.         case SKIP:
  778.         case AND:
  779.         case OR:
  780.         case CONST_STR:
  781.             f++;
  782.             break;
  783.         case CONST_INT:
  784.             f+=sizeof(long);
  785.             break;
  786.         case CONST_FLT:
  787.             f+=sizeof(double);
  788.             break;
  789.         case VAR:
  790.             f+=sizeof(struct var *);
  791.             break;
  792.         case R_CELL:
  793.         case R_CELL|ROWREL:
  794.         case R_CELL|COLREL:
  795.         case R_CELL|ROWREL|COLREL:
  796.             f+=EXP_ADD;
  797.             break;
  798.         case RANGE:
  799.         case RANGE|LRREL:
  800.         case RANGE|LRREL|LCREL:
  801.         case RANGE|LRREL|LCREL|HCREL:
  802.         case RANGE|LRREL|HCREL:
  803.         case RANGE|LRREL|HRREL:
  804.         case RANGE|LRREL|HRREL|LCREL:
  805.         case RANGE|LRREL|HRREL|LCREL|HCREL:
  806.         case RANGE|LRREL|HRREL|HCREL:
  807.         case RANGE|HRREL:
  808.         case RANGE|HRREL|LCREL:
  809.         case RANGE|HRREL|LCREL|HCREL:
  810.         case RANGE|HRREL|HCREL:
  811.         case RANGE|LCREL:
  812.         case RANGE|LCREL|HCREL:
  813.         case RANGE|HCREL:
  814.             f+=EXP_ADD_RNG;
  815.             break;
  816.         case F_PRINTF:
  817.         case F_CONCAT:
  818.         case F_ONEOF:
  819.         case F_STRSTR:
  820.         case F_EDIT:
  821.         case AREA_SUM:
  822.         case AREA_PROD:
  823.         case AREA_AVG:
  824.         case AREA_STD:
  825.         case AREA_MAX:
  826.         case AREA_MIN:
  827.         case AREA_CNT:
  828.         case AREA_VAR:
  829.             f++;
  830.             break;
  831.         default:
  832.             break;
  833.         }
  834.     } */
  835.   free (form);
  836. }
  837.  
  838. /* This tries to tell if a byte-compiled expression is a constant.  If it
  839.    is a constant, we can free it, and never try to recompute its value.
  840.    This returns non-zero if the expression is constant.*/
  841. int
  842. is_constant (bytes)
  843.      unsigned char *bytes;
  844. {
  845.   /* It's constant, but it's already been dealt with.
  846.        Pretend it isn't. */
  847.   if (!bytes)
  848.     return 0;
  849.  
  850.   switch (bytes[0])
  851.     {
  852.     case CONST_ERR:
  853.       return (bytes[3] == 0 && !strcmp ((char *) bytes + 4, ename[bytes[2]]));
  854.     case CONST_INT:
  855.       return bytes[sizeof (long) + 1] == ENDCOMP;
  856.     case CONST_FLT:
  857.       return bytes[sizeof (double) + 1] == ENDCOMP;
  858.     case CONST_STR:
  859.       return bytes[2] == ENDCOMP;
  860.     case F_TRUE:
  861.     case F_FALSE:
  862.     case CONST_INF:
  863.     case CONST_NINF:
  864.     case CONST_NAN:
  865.       return bytes[1] == ENDCOMP;
  866.     default:
  867.       return 0;
  868.     }
  869. }
  870.